﻿#pragma once
#include <map>
#include <string>
#include <vector>
#include <functional>
#include "../ssSingleton.h"
#include "../ssObject.h"
#include "ssClassFeild.h"
#include "ssClassMethod.h"

namespace StarSeeker
{

typedef ssObject* (*createObject_t)(void);

class ssClassFactory
{
	friend class ssSingle<ssClassFactory>;
public:
	struct ssClassData
	{
		createObject_t createFunc;
		std::vector<ssClassFeild> feilds;
	};
public:
    void RegisterClass(const std::string& className, createObject_t method);
	ssObject* CreateClass(const std::string& className);

	void RegisterClassField(const std::string& className, const std::string& fieldName, const std::string& fieldType, size_t offset);
	size_t GetFieldCount(const std::string& className);
	ssClassFeild* GetFeild(const std::string& className, size_t pos);
	ssClassFeild* GetFeild(const std::string& className, const std::string& fieldName);

	void RegisterClassMethod(const std::string& className, const std::string& methodName, uintptr_t method);
	size_t GetMethodCount(const std::string& className);
	ssClassMethod* GetMethod(const std::string& className, size_t pos);
	ssClassMethod* GetMethod(const std::string& className, const std::string& methodName);
private:
	ssClassFactory() {}
	~ssClassFactory() {}
private:
	std::map<std::string, createObject_t>				m_classMap;
	std::map<std::string, std::vector<ssClassFeild> >	m_classFeilds;
	std::map<std::string, std::vector<ssClassMethod> >	m_classMethods;
};

class ssClassRegister
{
public:
	ssClassRegister(const std::string& className, createObject_t method);
	ssClassRegister(const std::string& className, const std::string& fieldName, const std::string& fieldType, size_t offset);
	ssClassRegister(const std::string& className, const std::string& methodName, uintptr_t method);
};


#define SS_REGISTER_CLASS(className) ssObject* g_create_object_##className() {\
	ssObject* obj = new className();\
	obj->m_className = #className;\
	return obj;\
}\
ssClassRegister g_class_register_##className(#className, g_create_object_##className);

#define SS_REGISTER_CLASS_FIELD(className, fieldName, fieldType) ssClassRegister g_class_register_##className##_##fieldName(#className, #fieldName, #fieldType, (size_t)&(((className*)0)->fieldName));

#define SS_REGISTER_CLASS_METHOD(className, methodName, returnType, ...) std::function<returnType(className*, ##__VA_ARGS__)> g_##className##_##methodName = &className::methodName; \
    ssClassRegister g_class_register_##className##_##methodName(#className, #methodName, (uintptr_t)&(g_##className##_##methodName));

}
